<template>
<div class="personnel-table">
  <table class="table head">
    <colgroup>
      <col class="col" v-for="{ width, label } in table.head" :key="label" :style="{ width: width + 'px' }" />
    </colgroup>
    <thead>
      <tr class="tr">
        <th class="th" v-for="{ label } in table.head" :key="label">
          <div class="content">
            {{ label }}
          </div>
        </th>
      </tr>
    </thead>
  </table>

  <div class="body-wrapper">
    <!-- <VueSeamlessScroll style="height: 100%; overflow: hidden" :data="table.data" v-bind="seamlessScrollOption"> -->
    <table class="table body">
      <colgroup>
        <col class="col" v-for="{ width, label } in table.head" :key="label" :style="{ width: width + 'px' }" />
      </colgroup>
      <tbody>
        <tr class="tr" v-for="(d, index) in table.data" :key="index" @mouseenter="table.mouseenter(index)"
          @mouseleave="table.mouseleave(index)">
          <td class="td" v-for="{ prop, locate } in table.head" :key="prop">
            <template v-if="prop === 'serialNumber'">
              <div class="content">
                {{ index + 1 }}
                <!-- <div class="serial-number"> {{ index + 1 < 10 ? `0${index + 1}` : index + 1 }} </div> -->
              </div>

            </template>
            <template v-else-if="prop === 'locate'">
              <div class="content" @click="locate(d.coord)">
                <el-icon>
                  <Location />
                </el-icon>
              </div>
            </template>

            <template v-else>
              <div class="content">
                {{ d[prop] }}
              </div>
            </template>
          </td>
        </tr>
      </tbody>
    </table>
    <!-- <div class="interval-row"></div> -->
    <!-- </VueSeamlessScroll> -->
  </div>
</div>
</template>
<script setup>
// import { VueSeamlessScroll } from '@meruem117/vue-seamless-scroll'
import { reactive, onBeforeUnmount, inject } from 'vue'
import { rectangle, getRandomLonLatInRectangle, Personnel } from '../../../views/cesium-map/personnel'
import { waitUntilValueExist } from '../../../utils/unsorted'
import { en, fakerZH_CN as faker } from '@faker-js/faker';
import { tweenGroupAlongCesium } from '../../../views/cesium-map/index-cesium-map.js'
import * as Cesium from 'cesium'
import { Tween } from '@tweenjs/tween.js'


const table = reactive({
  data: [],
  head: [
    {
      prop: 'serialNumber',
      label: '序号',
      width: 40,
    },
    {
      prop: 'name',
      label: '姓名',
      width: 60,
    },
    {
      prop: 'department',
      label: '单位',
      // width: 160,
    },
    {
      prop: 'post',
      label: '职务',
      width: 60,
    },
    {
      prop: 'category',
      label: '类别',
      width: 60,
    },
    {
      prop: 'contact',
      label: '联系方式',
      width: 100,
    },
    {
      prop: 'locate',
      label: '定位',
      width: 50,
      locate({ longitude, latitude, height }) {
        cesiumViewer.camera.flyToBoundingSphere(new Cesium.BoundingSphere(
          Cesium.Cartesian3.fromRadians(longitude, latitude, height)
        ), {
          offset: new Cesium.HeadingPitchRange(0, -Math.PI / 4, 5000),
          duration: 1,
        })
      },
    }
  ],

  fetchData() {
    const md = Array(30).fill().map((_, index) => ({
      name: faker.person.fullName(),
      department: '国家电网华北第九所',
      post: '职务A',
      category: Math.random() > 0.3 ? '内部' : '外部',
      contact: 12345678900 + index,
      lonLat: getRandomLonLatInRectangle(rectangle),
    }))

    Promise.resolve(md)
      .then((data) => {
        if (data) {
          table.data = data
          waitUntilValueExist(() => window.cesiumViewer).then(() => {
            setTimeout(() => {
              // TODO: 这里有点问题，2000会出现错误，查找
              Personnel.instance = new Personnel().create(data)
            }, 3000)
          })
        } else {
          table.data = []
        }
      })
      .catch((err) => {
        table.data = []
      })
  },

  setup() {
    this.fetchData()
    /*
    const clearIntervalId = setInterval(
      () => {
        this.fetchData()
      },
      1000 * 60 * 5,
    )
    onBeforeUnmount(() => {
      clearInterval(clearIntervalId)
    })
      */
  },

  // TODO 闪几闪的动画效果
  runSparkleAnimation(entity, from, to, duration = 200) {
    // sparkAnimationMap
    if (!entity.sparkTween) {
      entity.sparkTween = new Tween(from)
        .to(to, duration)
        .repeat(Infinity)
        .onUpdate(({ x, pointSize }) => {
          const center = 0.5;
          const width = 0.25;
          const pct = gaussianPulse(x, center, width);
          entity.point.color = mixCesiumColor(Cesium.Color.RED, Cesium.Color.WHITE, pct)
        })
        .onComplete(() => {
          console.warn('闪烁完成')
        })
    }

    entity.sparkTween.start()
    tweenGroupAlongCesium.add(entity.sparkTween)
  },

  addSizeAnimation(entity, from, to, duration = 200) {
    const isForwared = from.pointSize < to.pointSize

    entity.tween = new Tween(from)
      .to(to, duration)
      .onUpdate(({ x, pointSize }) => {
        // const center = 0.5;
        // const width = 0.25;
        // const pct = gaussianPulse(x, center, width, 3);
        // entity.point.color = mixCesiumColor(Cesium.Color.RED, Cesium.Color.WHITE, pct)
        entity.point.pixelSize = pointSize
      })
      .onComplete(() => {
        if (isForwared) {
          entity.point.outlineWidth = 3
          entity.point.outlineColor = Cesium.Color.YELLOW
        } else {
          entity.point.outlineWidth = 2
          entity.point.outlineColor = Cesium.Color.WHITE
        }
        entity.point.color = Cesium.Color.RED
        entity.tween = tweenGroupAlongCesium.remove(entity.tween)
      })
      .start()
    tweenGroupAlongCesium.add(entity.tween)
  },

  mouseenter(index) {
    if (!window.cesiumViewer) return
    if (!Personnel.instance) return
    const { dataSource } = Personnel.instance.ml
    const entity = dataSource.entities.values.find(entity => entity.id === index)

    if (!entity) return

    entity.point.color = new Cesium.Color(1.0, 1.0, 0, 1)
    if (entity.tween) {
      entity.tween.stop()
      entity.tween = tweenGroupAlongCesium.remove(entity.tween)
    }
    this.addSizeAnimation(entity, { x: 0.3, pointSize: 10 }, { x: 0.7, pointSize: 16 })
    this.runSparkleAnimation(entity, { x: 0.3 }, { x: 0.7 })
  },

  mouseleave(index) {
    if (!window.cesiumViewer) return
    if (!Personnel.instance) return
    const { dataSource } = Personnel.instance.ml
    const entity = dataSource.entities.values.find(entity => entity.id === index)
    if (!entity) return
    entity.point.color = new Cesium.Color()
    if (entity.tween) {
      entity.tween.stop()
      entity.tween = tweenGroupAlongCesium.remove(entity.tween)
    }
    if (entity.sparkTween) {
      entity.sparkTween.stop()
      entity.sparkTween = tweenGroupAlongCesium.remove(entity.sparkTween)
    }

    this.addSizeAnimation(entity, { x: 0.0, pointSize: 16 }, { x: 0.0, pointSize: 10 })
  }

})

table.setup()

// 高斯
function gaussianPulse(x, center, width, times = 1) {
  // x = x * times - parseInt(x * times)
  return Math.exp(-Math.pow((x - center) / width, 2.0));
}

// 类似 shader 中的 mix 函数
function mixCesiumColor(color1, color2, factor) {
  return new Cesium.Color(
    Cesium.Math.lerp(color1.red, color2.red, factor),
    Cesium.Math.lerp(color1.green, color2.green, factor),
    Cesium.Math.lerp(color1.blue, color2.blue, factor),
    Cesium.Math.lerp(color1.alpha, color2.alpha, factor)
  );
}



</script>

<style lang="scss" scoped>
@use '../../../assets/styles/common/_util.scss' as util;

.personnel-table {
  height: 100%;
  --tr-content-height: 30px;
  --tr-height: calc(var(--tr-content-height) + var(--tr-padding-top, 0px));
  font-family: MicrosoftYaHei;
  // todo
  font-size: 14px;


  .table {


    table-layout: fixed;
    border-spacing: 0px;

    .th,
    .td {
      padding: 0;

      .content {
        height: 100%;
        @include util.ellipsis;
        display: grid;
        place-items: center;
      }
    }

    &.head {
      width: 100%;
      padding-right: 8px;

      .th {

        height: var(--tr-content-height);
        font-weight: normal;
        font-stretch: normal;
        // color: #a5e9fb;
        // background-color: rgba(0, 101, 142, 0.59);
      }
    }

    &.body {
      width: 100%;

      .tr:nth-child(even) {
        background-color: var(--row-stripe-bg-color);
      }


      .td {
        height: var(--tr-height);
        cursor: pointer;
        padding-top: var(--tr-padding-top);

      }


      .tr:hover {
        .td {
          color: #f6ac63;
        }
      }
    }
  }

  .body-wrapper {
    // --row-length: v-bind(rowLength);
    // height: calc(var(--tr-height) * var(--row-length));
    height: calc(100% - var(--tr-content-height));
    scrollbar-gutter: stable;
    overflow-y: hidden;
    overflow-x: hidden;

    &:hover {
      overflow-y: auto;
    }

    .interval-row {
      height: var(--tr-height);
    }
  }
}
</style>
